from flask import Flask, render_template, request, jsonify, send_file
import os
import tempfile
import threading
import queue
import uuid
from datetime import datetime
from werkzeug.utils import secure_filename
from pathlib import Path

# 导入现有功能模块
from update_executor import JarUpdaterCore
from excel_parser import ExcelParser

# 导入Class匹配功能模块
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from services.jar_service import JarSearchService
from services.excel_service import ExcelService
from services.progress_service import progress_service
from utils_class_match.file_utils import secure_filename as secure_filename_class, extract_class_name

# 导入JAR包对比功能模块
from services.jar_compare_service import JarCompareService
from services.compare_excel_service import CompareExcelService

# 导入补丁检查功能模块
from services.patch_check_service import PatchCheckService

# 获取项目根目录（web_app.py 在 src/ 目录下，需要返回上一级）
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates')
STATIC_DIR = os.path.join(BASE_DIR, 'static')

app = Flask(__name__, 
            template_folder=TEMPLATE_DIR,
            static_folder=STATIC_DIR)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['UPLOAD_FOLDER'] = tempfile.gettempdir()
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024  # 500MB (增加以支持Class匹配功能)
app.config['RESULTS_FOLDER'] = os.path.join(BASE_DIR, 'results')
app.config['CLASS_MATCH_UPLOAD_FOLDER'] = os.path.join(BASE_DIR, 'uploads')
app.config['JAR_COMPARE_UPLOAD_FOLDER'] = os.path.join(BASE_DIR, 'uploads', 'jar_compare')
app.config['PATCH_CHECK_UPLOAD_FOLDER'] = os.path.join(BASE_DIR, 'uploads', 'patch_check')

# 确保目录存在
os.makedirs(app.config['RESULTS_FOLDER'], exist_ok=True)
os.makedirs(app.config['CLASS_MATCH_UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['JAR_COMPARE_UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['PATCH_CHECK_UPLOAD_FOLDER'], exist_ok=True)

# 允许的文件扩展名
ALLOWED_JAR_EXTENSIONS = {'jar'}
ALLOWED_ZIP_EXTENSIONS = {'zip', 'rar'}
ALLOWED_EXCEL_EXTENSIONS = {'xlsx', 'xls'}

# 存储更新任务的字典
update_tasks = {}

class WebInteractiveGUI:
    """Web环境下的交互GUI适配器，用于处理用户选择"""
    def __init__(self, task_id):
        self.task_id = task_id

    def choose_zip_mapping(self, filename, dest_path, candidates):
        """当有多个候选文件时，等待Web用户选择"""
        task = update_tasks.get(self.task_id)
        if not task:
            return None
        
        choice_id = str(uuid.uuid4())
        choice_data = {
            'id': choice_id,
            'type': 'zip_choice',
            'filename': filename,
            'dest_path': dest_path,
            'candidates': [
                {
                    'path': c['path'],
                    'timestamp': datetime.fromtimestamp(c['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
                }
                for c in candidates
            ],
            'response': None,
            'event': threading.Event()
        }
        
        if 'pending_choices' not in task:
            task['pending_choices'] = {}
        task['pending_choices'][choice_id] = choice_data
        
        # 等待用户响应（最多5分钟）
        if choice_data['event'].wait(timeout=300):
            return choice_data['response']
        else:
            # 超时默认选择第一个
            return 0

class WebLogCallback:
    def __init__(self, task_id):
        self.task_id = task_id
        self.log_queue = update_tasks[task_id]['log_queue']
        
    def __call__(self, message):
        timestamp = datetime.now().strftime('%H:%M:%S')
        self.log_queue.put(f'[{timestamp}] {message}')

class WebStatusVar:
    def __init__(self, task_id):
        self.task_id = task_id
        
    def set(self, status):
        update_tasks[self.task_id]['status'] = status

class WebProgressVar:
    def __init__(self, task_id):
        self.task_id = task_id
        
    def set(self, progress):
        update_tasks[self.task_id]['progress'] = progress

# 检查文件类型
def allowed_file(filename, allowed_extensions):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in allowed_extensions

# 保存上传的文件
def save_uploaded_file(file, directory):
    filename = secure_filename(file.filename)
    filepath = os.path.join(directory, filename)
    file.save(filepath)
    return filepath

# 清理任务资源
def cleanup_task(task_id):
    if task_id in update_tasks:
        task_dir = update_tasks[task_id].get('task_dir')
        if task_dir and os.path.exists(task_dir):
            import shutil
            try:
                shutil.rmtree(task_dir)
            except:
                pass
        del update_tasks[task_id]

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/update', methods=['POST'])
def update_jar():
    # 检查是否有文件上传
    if 'jar_file' not in request.files or 'zip_file' not in request.files or 'excel_file' not in request.files:
        return jsonify({'error': '请上传所有必需的文件'}), 400
    
    jar_file = request.files['jar_file']
    zip_file = request.files['zip_file']
    excel_file = request.files['excel_file']
    
    # 检查文件名是否为空
    if jar_file.filename == '' or zip_file.filename == '' or excel_file.filename == '':
        return jsonify({'error': '请选择所有必需的文件'}), 400
    
    # 检查文件类型
    if not allowed_file(jar_file.filename, ALLOWED_JAR_EXTENSIONS) or \
       not allowed_file(zip_file.filename, ALLOWED_ZIP_EXTENSIONS) or \
       not allowed_file(excel_file.filename, ALLOWED_EXCEL_EXTENSIONS):
        return jsonify({'error': '不支持的文件类型'}), 400
    
    # 创建任务ID
    task_id = str(uuid.uuid4())
    
    # 创建临时目录
    task_dir = os.path.join(app.config['UPLOAD_FOLDER'], f'jar_update_{task_id}')
    os.makedirs(task_dir, exist_ok=True)
    
    # 保存上传的文件
    jar_path = save_uploaded_file(jar_file, task_dir)
    zip_path = save_uploaded_file(zip_file, task_dir)
    excel_path = save_uploaded_file(excel_file, task_dir)
    
    # 设置输出路径
    output_dir = os.path.join(task_dir, 'output')
    os.makedirs(output_dir, exist_ok=True)
    jar_name = secure_filename(jar_file.filename)
    name, ext = os.path.splitext(jar_name)
    # 修改这一行，使用正确的datetime方法
    today = datetime.today().strftime('%Y%m%d')
    output_path = os.path.join(output_dir, f'{name}_{today}{ext}')
    
    # 初始化任务状态
    update_tasks[task_id] = {
        'status': '准备中',
        'progress': 0,
        'log_queue': queue.Queue(),
        'logs': [],
        'output_path': output_path,
        'report_path': os.path.join(output_dir, 'UPDATE_REPORT.txt'),
        'task_dir': task_dir,
        'pending_choices': {}
    }
    
    # 解析Excel文件
    excel_parser = ExcelParser()
    replace_info_list, msg = excel_parser.parse_replace_info(excel_path)
    
    if not replace_info_list:
        cleanup_task(task_id)
        return jsonify({'error': f'Excel解析错误: {msg}'}), 400
    
    # 在新线程中执行更新操作
    threading.Thread(
        target=perform_web_update,
        args=(task_id, jar_path, zip_path, excel_path, output_path, replace_info_list),
        daemon=True
    ).start()
    
    return jsonify({'task_id': task_id})

@app.route('/status/<task_id>')
def get_status(task_id):
    if task_id not in update_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    task = update_tasks[task_id]
    
    # 获取新的日志消息
    new_logs = []
    while not task['log_queue'].empty():
        try:
            new_logs.append(task['log_queue'].get_nowait())
        except queue.Empty:
            break
    
    task['logs'].extend(new_logs)
    
    # 检查是否有待处理的选择
    pending_choice = None
    if 'pending_choices' in task:
        for choice_id, choice in task['pending_choices'].items():
            if choice['response'] is None:
                pending_choice = {
                    'id': choice_id,
                    'type': choice['type'],
                    'filename': choice['filename'],
                    'dest_path': choice['dest_path'],
                    'candidates': choice['candidates']
                }
                break
    
    return jsonify({
        'status': task['status'],
        'progress': task['progress'],
        'new_logs': new_logs,
        'is_complete': task['status'] in ['更新完成', '更新失败'],
        'pending_choice': pending_choice
    })

@app.route('/choice/<task_id>', methods=['POST'])
def submit_choice(task_id):
    """接收用户对多候选文件的选择"""
    if task_id not in update_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    data = request.get_json()
    choice_id = data.get('choice_id')
    selected_index = data.get('selected_index')
    
    # 添加日志
    print(f"[DEBUG] 接收到选择: task_id={task_id}, choice_id={choice_id}, selected_index={selected_index}, type={type(selected_index)}")
    
    if choice_id is None or selected_index is None:
        return jsonify({'error': '缺少必要参数'}), 400
    
    task = update_tasks[task_id]
    if 'pending_choices' not in task or choice_id not in task['pending_choices']:
        return jsonify({'error': '选择ID不存在'}), 404
    
    choice_data = task['pending_choices'][choice_id]
    print(f"[DEBUG] 设置响应索引: {selected_index}")
    choice_data['response'] = selected_index
    choice_data['event'].set()
    
    print(f"[DEBUG] 选择已提交成功")
    return jsonify({'success': True, 'selected_index': selected_index})

@app.route('/download/<task_id>/jar')
def download_jar(task_id):
    if task_id not in update_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    task = update_tasks[task_id]
    
    if not os.path.exists(task['output_path']):
        return jsonify({'error': '更新后的JAR文件不存在'}), 404
    
    return send_file(task['output_path'], as_attachment=True)

@app.route('/download/<task_id>/report')
def download_report(task_id):
    if task_id not in update_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    task = update_tasks[task_id]
    
    # 尝试在output目录和jar_temp_dir中查找报告
    report_paths = [
        task['report_path'],
        os.path.join(task['task_dir'], 'jar_contents', 'UPDATE_REPORT.txt'),
        os.path.dirname(os.path.dirname(task['output_path'])) + '/UPDATE_REPORT.txt'
    ]
    
    for report_path in report_paths:
        if os.path.exists(report_path):
            return send_file(report_path, as_attachment=True)
    
    return jsonify({'error': '更新报告不存在'}), 404

def perform_web_update(task_id, jar_path, zip_path, excel_path, output_path, replace_info_list):
    task = update_tasks.get(task_id)
    if not task:
        return

    status_var = WebStatusVar(task_id)
    log_callback = WebLogCallback(task_id)
    progress_var = WebProgressVar(task_id)

    try:
        # 更新状态
        status_var.set('更新中')
        log_callback('开始JAR包更新流程')

        # 创建JarUpdaterCore实例并传入Web交互GUI
        web_gui = WebInteractiveGUI(task_id)
        updater = JarUpdaterCore(gui=web_gui)

        # 执行更新 - 修复参数名称
        success = updater.perform_update(
            base_jar_path=jar_path,
            update_zip_path=zip_path,
            excel_path=excel_path,
            output_path=output_path,
            replace_info_list=replace_info_list,
            status_var=status_var,
            log_callback=log_callback,
            progress_var=progress_var,
            folder_replace_mode=False
        )
        
        if success:
            status_var.set('更新完成')
            log_callback('JAR包更新成功')
        else:
            status_var.set('更新失败')
            log_callback('JAR包更新失败')
            
    except Exception as e:
        status_var.set('更新失败')
        log_callback(f'更新过程中发生错误: {str(e)}')
    
    # 注意：任务资源会在前端下载完成后清理

# ==================== Class路径匹配功能路由 ====================

@app.route('/class-match/upload', methods=['POST'])
def class_match_upload():
    """处理Class匹配文件上传"""
    if 'jar_file' not in request.files or 'class_files' not in request.files:
        return jsonify({'error': '缺少必要的文件'}), 400
    
    jar_file = request.files['jar_file']
    class_files = request.files.getlist('class_files')
    
    if jar_file.filename == '':
        return jsonify({'error': '未选择jar文件'}), 400
    
    if not class_files or all(f.filename == '' for f in class_files):
        return jsonify({'error': '未选择class文件'}), 400
    
    # 生成唯一的任务ID
    import time
    task_id = f"task_{int(time.time() * 1000)}"
    
    try:
        # 保存jar文件
        jar_filename = secure_filename_class(jar_file.filename)
        jar_path = os.path.join(
            app.config['CLASS_MATCH_UPLOAD_FOLDER'], 
            f"{task_id}_{jar_filename}"
        )
        jar_file.save(jar_path)
        
        # 提取文件名列表（支持所有文件类型）
        file_names = []
        uploaded_file_names = []  # 保存上传的完整文件名列表（用于未匹配文件）
        for class_file in class_files:
            if class_file.filename:
                filename = secure_filename_class(class_file.filename)
                uploaded_file_names.append(filename)
                # 提取文件名（不含扩展名）用于匹配
                file_name = extract_class_name(filename)
                file_names.append(file_name)
        
        if not file_names:
            return jsonify({'error': '没有有效的文件'}), 400
        
        # 获取配置值（在应用上下文中获取，避免在线程中访问current_app）
        upload_folder = app.config['CLASS_MATCH_UPLOAD_FOLDER']
        results_folder = app.config['RESULTS_FOLDER']
        
        # 在后台线程中处理匹配
        def process_match():
            try:
                # 初始化进度
                progress_service.init_progress(task_id, total=0)
                progress_service.update_progress(task_id, status='starting')
                
                # 创建JAR搜索服务
                jar_service = JarSearchService(upload_folder)
                
                # 搜索匹配
                matches = jar_service.search_in_jar(
                    jar_path, 
                    file_names, 
                    Path(jar_filename).stem, 
                    task_id
                )
                
                # 找出匹配上的文件名（完整文件名和文件名不含扩展名都考虑）
                matched_file_names = set()
                for match in matches:
                    matched_file_names.add(match['filename'])
                    # 也添加不含扩展名的文件名，用于匹配
                    if '.' in match['filename']:
                        matched_file_names.add(match['filename'].rsplit('.', 1)[0])
                
                # 找出未匹配的文件（检查完整文件名和文件名不含扩展名）
                unmatched_files = []
                for filename in uploaded_file_names:
                    # 检查完整文件名和文件名不含扩展名是否都在匹配结果中
                    file_name_no_ext = filename.rsplit('.', 1)[0] if '.' in filename else filename
                    if filename not in matched_file_names and file_name_no_ext not in matched_file_names:
                        unmatched_files.append(filename)
                
                # 生成Excel文件（包含匹配结果和未匹配文件）
                excel_filename = f"{task_id}_results.xlsx"
                excel_path = os.path.join(results_folder, excel_filename)
                
                excel_service = ExcelService()
                excel_service.generate_excel(matches, unmatched_files, excel_path)
                
                # 更新进度
                progress_service.update_progress(task_id, status='completed')
                progress_service.set_excel_filename(task_id, excel_filename)
            
            except Exception as e:
                progress_service.update_progress(task_id, status=f'error: {str(e)}')
            
            finally:
                # 清理上传的jar文件
                try:
                    if os.path.exists(jar_path):
                        os.remove(jar_path)
                except:
                    pass
        
        # 启动后台处理线程
        thread = threading.Thread(target=process_match)
        thread.daemon = True
        thread.start()
        
        return jsonify({
            'task_id': task_id,
            'message': '文件上传成功，开始处理'
        })
    
    except Exception as e:
        return jsonify({'error': f'上传失败: {str(e)}'}), 500

@app.route('/class-match/progress/<task_id>')
def class_match_get_progress(task_id):
    """获取Class匹配处理进度"""
    if not progress_service.is_task_exists(task_id):
        return jsonify({'error': '任务不存在'}), 404
    
    progress = progress_service.get_progress(task_id)
    return jsonify(progress)

@app.route('/class-match/download/<task_id>')
def class_match_download_excel(task_id):
    """下载Class匹配Excel结果文件"""
    if not progress_service.is_task_exists(task_id):
        return jsonify({'error': '任务不存在'}), 404
    
    if not progress_service.is_task_completed(task_id):
        return jsonify({'error': '处理未完成'}), 400
    
    excel_filename = progress_service.get_excel_filename(task_id)
    if not excel_filename:
        return jsonify({'error': '文件不存在'}), 404
    
    excel_path = os.path.join(app.config['RESULTS_FOLDER'], excel_filename)
    if not os.path.exists(excel_path):
        return jsonify({'error': '文件不存在'}), 404
    
    return send_file(excel_path, as_attachment=True, download_name=excel_filename)

# ==================== JAR包对比功能 ====================

@app.route('/jar-compare/upload', methods=['POST'])
def jar_compare_upload():
    """上传两个JAR包进行对比"""
    try:
        # 检查是否有文件
        if 'jar1' not in request.files or 'jar2' not in request.files:
            return jsonify({'error': '请上传两个JAR包文件'}), 400
        
        jar1_file = request.files['jar1']
        jar2_file = request.files['jar2']
        
        # 检查文件名
        if jar1_file.filename == '' or jar2_file.filename == '':
            return jsonify({'error': '请选择两个JAR包文件'}), 400
        
        # 检查文件扩展名
        jar1_filename = jar1_file.filename
        jar2_filename = jar2_file.filename
        
        if not (jar1_filename.lower().endswith('.jar') and jar2_filename.lower().endswith('.jar')):
            return jsonify({'error': '只能上传JAR包文件'}), 400
        
        # 生成任务ID
        task_id = str(uuid.uuid4())
        
        # 保存上传的文件
        upload_folder = app.config['JAR_COMPARE_UPLOAD_FOLDER']
        jar1_path = os.path.join(upload_folder, f"{task_id}_jar1_{secure_filename_class(jar1_filename)}")
        jar2_path = os.path.join(upload_folder, f"{task_id}_jar2_{secure_filename_class(jar2_filename)}")
        
        jar1_file.save(jar1_path)
        jar2_file.save(jar2_path)
        
        # 初始化进度
        progress_service.init_progress(task_id, 0)
        progress_service.update_progress(task_id, status='starting')
        
        # 后台处理函数
        def process_compare():
            try:
                # 创建对比服务
                compare_service = JarCompareService(upload_folder)
                
                # 执行对比
                compare_result = compare_service.compare_jars(
                    jar1_path,
                    jar2_path,
                    jar1_filename,
                    jar2_filename,
                    task_id
                )
                
                # 生成Excel文件
                excel_filename = f"{task_id}_compare_results.xlsx"
                excel_path = os.path.join(app.config['RESULTS_FOLDER'], excel_filename)
                
                excel_service = CompareExcelService()
                excel_service.generate_excel(compare_result, excel_path)
                
                # 更新进度
                progress_service.update_progress(task_id, status='completed')
                progress_service.set_excel_filename(task_id, excel_filename)
            
            except Exception as e:
                progress_service.update_progress(task_id, status=f'error: {str(e)}')
            
            finally:
                # 清理上传的JAR文件
                try:
                    if os.path.exists(jar1_path):
                        os.remove(jar1_path)
                    if os.path.exists(jar2_path):
                        os.remove(jar2_path)
                except:
                    pass
        
        # 启动后台处理线程
        thread = threading.Thread(target=process_compare)
        thread.daemon = True
        thread.start()
        
        return jsonify({
            'task_id': task_id,
            'message': '文件上传成功，开始对比'
        })
    
    except Exception as e:
        return jsonify({'error': f'上传失败: {str(e)}'}), 500

@app.route('/jar-compare/progress/<task_id>')
def jar_compare_get_progress(task_id):
    """获取JAR包对比处理进度"""
    if not progress_service.is_task_exists(task_id):
        return jsonify({'error': '任务不存在'}), 404
    
    progress = progress_service.get_progress(task_id)
    return jsonify(progress)

@app.route('/jar-compare/download/<task_id>')
def jar_compare_download_excel(task_id):
    """下载JAR包对比Excel结果文件"""
    if not progress_service.is_task_exists(task_id):
        return jsonify({'error': '任务不存在'}), 404
    
    if not progress_service.is_task_completed(task_id):
        return jsonify({'error': '处理未完成'}), 400
    
    excel_filename = progress_service.get_excel_filename(task_id)
    if not excel_filename:
        return jsonify({'error': '文件不存在'}), 404
    
    excel_path = os.path.join(app.config['RESULTS_FOLDER'], excel_filename)
    if not os.path.exists(excel_path):
        return jsonify({'error': '文件不存在'}), 404
    
    return send_file(excel_path, as_attachment=True, download_name=excel_filename)

# ==================== 补丁检查功能 ====================

# 存储补丁检查任务结果
patch_check_tasks = {}

@app.route('/patch-check/upload', methods=['POST'])
def patch_check_upload():
    """上传JAR包、Excel文件和压缩包进行补丁检查"""
    try:
        # 检查是否有文件
        if 'jar_file' not in request.files or 'excel_file' not in request.files or 'zip_file' not in request.files:
            return jsonify({'error': '请上传JAR包、Excel文件和压缩包'}), 400
        
        jar_file = request.files['jar_file']
        excel_file = request.files['excel_file']
        zip_file = request.files['zip_file']
        
        # 检查文件名
        if jar_file.filename == '' or excel_file.filename == '' or zip_file.filename == '':
            return jsonify({'error': '请选择所有必需的文件'}), 400
        
        # 检查文件扩展名
        if not jar_file.filename.lower().endswith('.jar'):
            return jsonify({'error': 'JAR包文件格式不正确'}), 400
        if not allowed_file(excel_file.filename, ALLOWED_EXCEL_EXTENSIONS):
            return jsonify({'error': 'Excel文件格式不正确'}), 400
        if not allowed_file(zip_file.filename, ALLOWED_ZIP_EXTENSIONS):
            return jsonify({'error': '压缩包文件格式不正确'}), 400
        
        # 生成任务ID
        task_id = str(uuid.uuid4())
        
        # 保存上传的文件
        upload_folder = app.config['PATCH_CHECK_UPLOAD_FOLDER']
        task_dir = os.path.join(upload_folder, task_id)
        os.makedirs(task_dir, exist_ok=True)
        
        jar_path = os.path.join(task_dir, secure_filename_class(jar_file.filename))
        excel_path = os.path.join(task_dir, secure_filename_class(excel_file.filename))
        zip_path = os.path.join(task_dir, secure_filename_class(zip_file.filename))
        
        jar_file.save(jar_path)
        excel_file.save(excel_path)
        zip_file.save(zip_path)
        
        # 解析Excel文件
        excel_parser = ExcelParser()
        excel_data, msg = excel_parser.parse_replace_info(excel_path)
        
        if not excel_data:
            # 清理文件
            try:
                import shutil
                shutil.rmtree(task_dir, ignore_errors=True)
            except:
                pass
            return jsonify({'error': f'Excel解析错误: {msg}'}), 400
        
        # 初始化任务
        patch_check_tasks[task_id] = {
            'status': 'processing',
            'result': None,
            'task_dir': task_dir
        }
        
        # 初始化进度
        progress_service.init_progress(task_id, 0)
        progress_service.update_progress(task_id, status='starting')
        
        # 后台处理函数
        def process_check():
            try:
                # 创建补丁检查服务
                check_service = PatchCheckService(upload_folder)
                
                # 执行检查
                check_result = check_service.check_patch(
                    jar_path,
                    zip_path,
                    excel_data,
                    task_id
                )
                
                # 保存结果
                patch_check_tasks[task_id]['result'] = check_result
                patch_check_tasks[task_id]['status'] = 'completed'
                
                # 更新进度
                progress_service.update_progress(task_id, status='completed')
            
            except Exception as e:
                patch_check_tasks[task_id]['status'] = 'error'
                patch_check_tasks[task_id]['error'] = str(e)
                progress_service.update_progress(task_id, status=f'error: {str(e)}')
            
            finally:
                # 清理临时文件
                try:
                    import shutil
                    if os.path.exists(task_dir):
                        shutil.rmtree(task_dir, ignore_errors=True)
                except Exception as e:
                    print(f"清理临时文件失败: {e}")
        
        # 启动后台处理线程
        thread = threading.Thread(target=process_check)
        thread.daemon = True
        thread.start()
        
        return jsonify({
            'task_id': task_id,
            'message': '文件上传成功，开始检查'
        })
    
    except Exception as e:
        return jsonify({'error': f'上传失败: {str(e)}'}), 500

@app.route('/patch-check/progress/<task_id>')
def patch_check_get_progress(task_id):
    """获取补丁检查处理进度"""
    if task_id not in patch_check_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    task = patch_check_tasks[task_id]
    progress = progress_service.get_progress(task_id)
    
    if progress:
        progress['task_status'] = task['status']
        if task['status'] == 'completed' and task['result']:
            progress['completed'] = True
        elif task['status'] == 'error':
            progress['error'] = task.get('error', '未知错误')
    
    return jsonify(progress)

@app.route('/patch-check/result/<task_id>')
def patch_check_get_result(task_id):
    """获取补丁检查结果"""
    if task_id not in patch_check_tasks:
        return jsonify({'error': '任务不存在'}), 404
    
    task = patch_check_tasks[task_id]
    
    if task['status'] == 'processing':
        return jsonify({'error': '处理尚未完成'}), 400
    
    if task['status'] == 'error':
        return jsonify({'error': task.get('error', '未知错误')}), 500
    
    if task['status'] == 'completed' and task['result']:
        return jsonify(task['result'])
    
    return jsonify({'error': '结果不存在'}), 404

# ==================== 应用启动 ====================

# 启动应用
if __name__ == '__main__':
    # 默认在127.0.0.1:5000启动
    # app.run(debug=True)
    
    # 通过环境变量控制 debug 模式（后台运行时关闭 debug）
    debug_mode = os.getenv('WEBAPP_DEBUG', 'False').lower() == 'true'
    
    # 指定端口和主机的方式
    app.run(host='0.0.0.0', port=18081, debug=debug_mode)